'''
将图集根据json转化为序列帧图片
'''
import math
import os
import json
from PIL import Image, ImageTk
import tkinter as tk
from tkinter import filedialog, Entry, Button, StringVar

def create_window(parent):

    if parent is None:
        root = tk.Tk()
    else:
        root = tk.Toplevel(parent)
    global offX, offY
    offX = 60
    offY = 50

    # 裁剪图片边界区域
    global left_value, right_value, up_value, down_value
    left_value = 1
    right_value = 1
    up_value = 1
    down_value = 1

    global imgs_scale, scale_value, scale_index
    scale_value = 1
    imgs_scale = []
    scale_index = 0

    # 创建窗口
    root.title("序列帧图片转换器")
    root.config(bg="grey")
    root.geometry("1000x1000+0+0")

    # 图像绘制位置坐标
    canvas_scale = tk.Canvas(root, width=800, height=800, bg="gray")
    canvas_scale.place(x=offX + 70, y=offY + 100)

    def select_directory(entry_var):
        """弹出选择目录对话框"""
        directory = filedialog.askdirectory(parent=root)
        entry_var.set(directory)
        root.lift()

    # 第一行：按钮+输入框
    entry_scale_frame_path = StringVar()
    entry_path = Entry(root, textvariable=entry_scale_frame_path)
    entry_path.place(x=offX + 350, y=offY -27)
    button1 = Button(root, text="序列帧目录", command=lambda: select_directory(entry_scale_frame_path),
                           bg='skyblue')
    button1.place(x=offX + 500, y=offY -30)

    # 第二行：按钮+输入框
    entry_scale_target_path = StringVar()
    entry_path1 = Entry(root, textvariable=entry_scale_target_path)
    entry_path1.place(x=offX + 350, y=offY + 20)
    button2 = Button(root, text="输出目录", command=lambda: select_directory(entry_scale_target_path),
                           bg='skyblue')
    button2.place(x=offX + 500, y=offY + 23)

    # 第三行：按钮
    button3 = Button(root, text="转换预览", command=lambda:load_images(),
                           bg='skyblue')
    button3.place(x=offX + 400, y=offY + 60)
    button4 = Button(root, text="导出",command=lambda: process_directory(entry_scale_frame_path,entry_scale_target_path),bg='skyblue')
    button4.place(x=offX + 500, y=offY + 60)

    def updateOrSave(output_sub_dir,index,back_image):
        if not output_sub_dir:
            imgs_scale.append(back_image)
        else:
            output_path = os.path.join(output_sub_dir, f"{index}.png")
            back_image.save(output_path)

    def SetImg(data,image_file,output_sub_dir):
        # 打开整图
        image = Image.open(image_file)

        # 裁剪小图并保存
        frames = data.get("frames", [])
        img = data.get("count", [])
        atlas = data.get("frames", {})
        mc = data.get("res", {})
        if len(frames) >0 and len(img)>0:
            for index, frame in enumerate(frames):
                x = frame["x"]
                y = frame["y"]
                w = frame["w"]
                h = frame["h"]
                sizeH = frame["sourceH"]
                sizeW = frame["sourceW"]
                offX = frame["offX"]
                offY = frame["offY"]
                back_image = Image.new("RGBA", (sizeW, sizeH))

                # 从整图中裁剪子图
                cropped_image = image.crop((x, y, x + w, y + h))
                back_image.paste(cropped_image, (int(offX), int(offY)))

                updateOrSave(output_sub_dir,index,back_image)

        if len(frames) == 0 and len(img) == 0:
            # 计算背景图像的大小，确保足够大以容纳所有偏移
            # min_x = min(frame["ox"] for frame in data.values())
            # min_y = min(frame["oy"] for frame in data.values())
            # max_x = max(frame["ox"] + frame["w"] for frame in data.values())
            # max_y = max(frame["oy"] + frame["h"] for frame in data.values())
            # for index, frame in sorted(data.items(), key=lambda item: int(item[0])):
            #     x = frame["x"]
            #     y = frame["y"]
            #     w = frame["w"]
            #     h = frame["h"]
            #     offX = frame["ox"]
            #     offY = frame["oy"]
            #     back_width = max_x - min_x
            #     back_height = max_y - min_y
            #     back_image = Image.new("RGBA", (back_width, back_height))

            for index, frame_data in mc.items():

                x = frame_data["x"]
                y = frame_data["y"]
                w = frame_data["w"]
                h = frame_data["h"]
                # sizeH = frame_data["sourceH"]
                # sizeW = frame_data["sourceW"]
                offX =0# frame_data["offX"]
                offY =0# frame_data["offY"]
                back_image = Image.new("RGBA", (w,h))


                # 从整图中裁剪子图
                cropped_image = image.crop((x, y, x + w, y + h))
                paste_x = offX #- min_x
                paste_y = offY #- min_y
                back_image.paste(cropped_image, (int(paste_x), int(paste_y)))

                #imgs_scale.append(back_image)
                updateOrSave(output_sub_dir, index, back_image)
        if len(frames) > 0 and len(img)==0:
            #atlas = data.get("frames", {})
            # for index, frame_data in atlas.items():
            #     frame = frame_data.get("frame", {})
            #     size = frame_data.get("sourceSize", {})
            #     sourceSize = frame_data.get("spriteSourceSize", {})
            #     x = frame["x"]
            #     y = frame["y"]
            #     w = frame["w"]
            #     h = frame["h"]
            #     sizeH = size["h"]
            #     sizeW = size["w"]
            #     offX = sourceSize["x"]
            #     offY = sourceSize["y"]
            #     back_image = Image.new("RGBA", (sizeW,sizeH))

            for index, frame_data in atlas.items():

                x = frame_data["x"]
                y = frame_data["y"]
                w = frame_data["w"]
                h = frame_data["h"]
                sizeH = frame_data["sourceH"]
                sizeW = frame_data["sourceW"]
                offX = frame_data["offX"]
                offY = frame_data["offY"]
                back_image = Image.new("RGBA", (sizeW,sizeH))



                # 从整图中裁剪子图
                cropped_image = image.crop((x, y, x + w, y + h))
                back_image.paste(cropped_image, (int(offX), int(offY)))
                updateOrSave(output_sub_dir, index, back_image)

    def process_directory(entry_scale_frame_path, entry_scale_target_path):
        """批量处理序列帧的裁剪"""
        input_dir = entry_scale_frame_path.get()  # 获取输入目录的字符串值
        output_dir = entry_scale_target_path.get()  # 获取输出目录的字符串值
        if not os.path.isdir(input_dir):
            print("输入目录不能为空。")
            return
        for sub_dir in os.listdir(input_dir):
            full_sub_dir = os.path.join(input_dir, sub_dir)
            # 只处理目录
            if not os.path.isdir(full_sub_dir):
                continue

            print(f"正在处理目录：{full_sub_dir}")

            image_files = []
            for file in os.listdir(full_sub_dir):
                if file.endswith(".png"):
                    image_files.append(os.path.join(full_sub_dir, file))

            i = 0
            for image_file in image_files:
                json_file = None
                for file in os.listdir(full_sub_dir):
                    cur_json_file = os.path.join(full_sub_dir, file)
                    if file.endswith(".json") and os.path.splitext(cur_json_file)[0] == os.path.splitext(image_file)[0]:
                        json_file = cur_json_file
                        break

                if not json_file or not image_file:
                    print(f"目录 {sub_dir} 缺少 JSON 或 PNG 文件，跳过处理。")
                    continue

                # 创建输出子目录
                output_sub_dir = os.path.join(output_dir, sub_dir, f"{sub_dir}_{i}")
                i += 1
                os.makedirs(output_sub_dir, exist_ok=True)
                # 加载 JSON 文件
                with open(json_file, "r") as file:
                    data = json.load(file)
                SetImg(data, image_file, output_sub_dir)
                
                print(f"目录 {sub_dir} 处理完成，结果保存至 {output_sub_dir}")

    def load_images():
        global imgs_scale, button_scale
        global button_scale_load, button_scale_sure, scale_value, input_folder, output_folder, imgs_scale_path
        """批量处理序列帧的裁剪"""
        input_dir = entry_scale_frame_path.get()  # 获取输入目录的字符串值

        if not os.path.isdir(input_dir):
            print("输入目录不能为空。")
            return

        for sub_dir in os.listdir(input_dir):
            full_sub_dir = os.path.join(input_dir, sub_dir)
            error_log=[]
            # 只处理目录
            if not os.path.isdir(full_sub_dir):
                continue

            print(f"正在处理目录：{full_sub_dir}")

            image_files = []
            for file in os.listdir(full_sub_dir):
                if file.endswith(".png"):
                    image_files.append(os.path.join(full_sub_dir, file))

            i = 0
            for image_file in image_files:
                json_file = None
                for file in os.listdir(full_sub_dir):
                    cur_json_file = os.path.join(full_sub_dir, file)
                    if file.endswith(".json") and os.path.splitext(cur_json_file)[0] == os.path.splitext(image_file)[0]:
                        json_file = cur_json_file
                        break

                if not json_file or not image_file:
                    print(f"目录 {sub_dir} 缺少 JSON 或 PNG 文件，跳过处理。")
                    continue
                i += 1
                try:
                    # 加载 JSON 文件
                    with open(json_file, "r") as file:
                        data = json.load(file)
                        SetImg(data, image_file, "")

                except(json.JSONDecodeError, UnicodeDecodeError) as e:
                    error_log.append((json_file, str(e)))
                    print(f"跳过错误文件: {json_file} - 原因: {e}")
                except Exception as e:
                    error_log.append((json_file, str(e)))
                    print(f"未知错误: {json_file} - {e}")
                # 打开整图
        update_frame_sclae()

    # 刷新帧率图片
    def update_frame_sclae():
        global imgs_scale, scale_index, photo, resized_img, name, root_after2
        if imgs_scale:
            canvas_scale.delete("all")
            length = len(imgs_scale)
            img_scale = imgs_scale[scale_index]
            #name = img_scale.filename.split("\\")[len(img_scale.filename.split("\\")) - 1]
            resize = [math.ceil(img_scale.size[0] * scale_value), math.ceil(img_scale.size[1] * scale_value)]
            resized_img = img_scale.resize(resize, Image.Resampling.LANCZOS)
            photo = ImageTk.PhotoImage(resized_img)
            x = int(photo.width() / 2)
            y = int(photo.height() / 2)

            canvas_scale.create_rectangle(x - photo.width() / 2, y - photo.height() / 2, x + photo.width() / 2,
                                          y + photo.height() / 2, fill="white", outline="black")
            canvas_scale.create_image(x, y, anchor=tk.CENTER, image=photo)

            canvas_scale.create_line(left_value, up_value, right_value, up_value, fill="red")
            canvas_scale.create_line(left_value, down_value, right_value, down_value, fill="red")
            canvas_scale.create_line(left_value, up_value, left_value, down_value, fill="red")
            canvas_scale.create_line(right_value, up_value, right_value, down_value, fill="red")

            scale_index = (scale_index + 1) % length  # 循环显示
        root_after2 = root.after(200, update_frame_sclae)
    if parent is None:
        root.mainloop()
if __name__ == "__main__":
    create_window(None)
